// h函数
const h = (tar,props,children) => {
  return {
    tar,
    props,
    children
  }
}

// mount函数
const mount = (vnode,container) => {
  // 1.创建vnode的tar
  const el = vnode.el = document.createElement(vnode.tar)
  // 2.给el添加属性
  if(vnode.props) {
    for(const key in vnode.props) {
      // 取出属性值
      const value = vnode.props[key]
      // 事件监听
      if(key.startsWith('on')) {
        el.addEventListener(key.slice(2).toLocaleLowerCase(),value)
      }else{
        el.setAttribute(key,value)
      }
    }
  }
  // 3.处理children
  if(typeof vnode.children === 'string') {
    // 如果是一个字符串直接插入
    el.textContent = vnode.children
  }else{
    // 插入其他虚拟节点
    vnode.children.forEach(item => {
      // 递归调用mount函数为各个vnode添加子节点
      mount(item,el)
    })
  }
  // 4.将el挂载到app节点
  container.appendChild(el)
}

// patch函数
const patch = (n1,n2) => {
  // n1为oldNode，n2为newNode
  if(n1.tar !== n2.tar) {  //n1和n2不是同一个节点
    // 获取父节点，之后将新节点挂载到父节点
    const n1ElParent = n1.el.parentElement
    n1ElParent.removeChild(n1.el)
    mount(n2,n1ElParent)
  }else{  //n1和n2是同一个节点
    const oldProps = n1.props || {}
    const newProps = n2.props || {}
    // 1.取出element对象, 并且在n2中进行保存
    const el = n2.el = n1.el;

    // 2.处理props
    for(const key in newProps) {  //将新的props搞上去
      const newValue = newProps[key]
      const oldValue = oldProps[key]
      if(newValue !== oldValue) {
        if(key.startsWith('on')) {  //处理函数
          el.addEventListener(key.slice(2).toLocaleLowerCase(),newValue)
        }else{  //不是函数
          el.setAttribute(key,newValue)
        }
      }
    }
    for(const key in oldProps) { //去除老的props
      const oldValue = oldProps[key]
      if(key.startsWith('on')) {  //移除老的事件监听
        el.removeEventListener(key.slice(2).toLocaleLowerCase(),oldValue)
      }
      if(!(key in newProps)) {
        el.removeAttribute(key)
      }
    }

    // 3.处理children
    const oldChildren = n1.children || []
    const newChildren = n2.children || []
    if(typeof newChildren === 'string') {
      if(typeof oldChildren === 'string') {  //新旧都是字符串，直接改成新的字符串
        el.textContent = newChildren
      }else {
        el.innerHTML = newChildren
      }
    }else{  //newChildren 是一个数组
      if(typeof oldChildren === 'string') {
        el.innerHTML = ''
        for(const item of newProps) {
          mount(item,el)
        }
      }else {  // oldChildren也是一个数组
        // 取出较短的进行patch操作
        let commonLength = Math.min(oldChildren.length,newChildren.length)
        for(let i=0;i<commonLength;i++) {
          patch(oldChildren[i],newChildren[i])
        }
        // 如果newChildren的长度更大
        if(oldChildren.length < newChildren.length) {
          newChildren.slice(oldChildren.length).forEach(item => {
            mount(item,el)
          })
        }
        // 如果oldChildren的长度更大，将更长的去除
        if(oldChildren.length > newChildren.length) {
          oldChildren.slice(newChildren.length).forEach(item => {
            el.removeChild(item.el)
          })
        }
      }
    }
  }
}